// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © EzAlgo

//@version=5
indicator("EzTrendlines",overlay = true)

//inputs
show_trendlines = input.bool(true, 'Show Trendlines', inline = 'tl_1',group='Trendlines')
upper_trendline_color        = input.color(#9598a1, '', inline = 'tl_1',group='Trendlines')
lower_trendline_color        = input.color(#9598a1, '', inline = 'tl_1',group='Trendlines')
extendLine      = input.bool(true, 'Extend', inline = 'tl_1',group='Trendlines')

linestyle_curr_inp = input.string(defval = 'Solid', title = "Style", options = ['Solid', 'Dotted', 'Dashed'],inline = "tl_3",group='Trendlines')
line_width_curr          = input.int(1, 'Width', step = 1, minval = 1,maxval = 4,inline = "tl_3",group='Trendlines')

pivLen_L          = input.int(20, 'Lookback', step = 1, minval = 1, inline ='tl_5',group='Trendlines')
pivLen_R          = pivLen_L//input.int(20, '/', step = 1, minval = 1, inline ='tl_5',group='Trendlines')

hideCrossed     = not(input.bool(true, 'Show Broken', inline = 'tl_2',group='Trendlines'))
broken_color_up        = input.color(#9598a1, '', inline = 'tl_2',group='Trendlines')
broken_color_down        = input.color(#9598a1, '', inline = 'tl_2',group='Trendlines')
extendLine_B      = input.bool(true, 'Extend', inline = 'tl_2',group='Trendlines')

show_signals     = input.bool(false, 'Show Signals', inline = 'tl_s',group='Trendlines')
broken_color_up_signal        = input.color(color.yellow, '', inline = 'tl_s',group='Trendlines')
broken_color_down_signal        = input.color(color.yellow, '', inline = 'tl_s',group='Trendlines')

maxLines        = input.int(3, 'Max Broken', step = 1, minval = 1, maxval = 50, inline = 'tl_2_B',group='Trendlines')
Source_tl        = input.string('Close', 'Mitigation', options = ['Close', 'High/Low'], inline ='tl_2_B',group='Trendlines')

linestyle_broken_inp = input.string(defval = 'Dashed', title = "Style (Broken)", options = ['Solid', 'Dotted', 'Dashed'],inline = "tl_2-1",group='Trendlines')
line_width_broken         = input.int(1, 'Width', step = 1, minval = 1,maxval = 4,inline = "tl_2-1",group='Trendlines')

lineStyle_curr= linestyle_curr_inp == 'Solid' ?  line.style_solid : linestyle_curr_inp == 'Dotted' ?  line.style_dotted : line.style_dashed
lineStyle_broken= linestyle_broken_inp == 'Solid' ?  line.style_solid : linestyle_broken_inp == 'Dotted' ?  line.style_dotted : line.style_dashed

s_close = request.security(ticker.standard(syminfo.tickerid), timeframe.period, close)
s_open = request.security(ticker.standard(syminfo.tickerid), timeframe.period, open)
s_high = request.security(ticker.standard(syminfo.tickerid), timeframe.period, high)
s_low = request.security(ticker.standard(syminfo.tickerid), timeframe.period, low)


var line[] pivot_high_array = array.new_line(),var line[] pivot_low_array = array.new_line()
ph_M = ta.pivothigh(s_high, pivLen_L, pivLen_R)
pl_M = ta.pivotlow(s_low, pivLen_L, pivLen_R)
ph = ta.pivothigh(s_high, pivLen_L, pivLen_R)
pl = ta.pivotlow(s_low, pivLen_L, pivLen_R)

var float prev_close_H = na, var float curr_close_H = na
var float prev_close_L = na, var float curr_close_L = na

var int X_prev_low = na, var float Y_prev_low = na, var int X_curr_low = na, var float Y_curr_low = na
var int X_curr_high = na, var float Y_curr_high = na, var int X_prev_high = na, var float Y_prev_high = na


maxLines        := hideCrossed ? 0 : maxLines
tl_array_size_up    = maxLines/2
tl_array_size_dn    = maxLines%2==0? maxLines/2 : (maxLines/2)+1

//functions

newTrendLine(ptype, x1, y1, x2, y2)=>
    new_trendline = line.new(x1, y1, x2, y2, extend = extendLine ? extend.right : extend.none, color = ptype == 'ph' ? upper_trendline_color : lower_trendline_color, width = line_width_curr,style = lineStyle_curr,xloc = xloc.bar_index)
    if ptype == 'ph'
        pivot_high_array.unshift(new_trendline)
    else
        pivot_low_array.unshift(new_trendline)

SlopeOfLine(line)=>
    slopePh = (line.get_y2(line) - line.get_y1(line))/(line.get_x2(line) -line.get_x1(line))
    extendedPh = line.get_y2(line) - slopePh * (line.get_x2(line) - bar_index)
    extendedPh

up_trend_line_formed= false
down_trend_line_formed = false

if pl
    X_prev_low := X_curr_low, Y_prev_low := Y_curr_low, prev_close_L := curr_close_L
    X_curr_low := bar_index[pivLen_R], Y_curr_low := s_low[pivLen_R], curr_close_L:= s_close[pivLen_R]
    if Y_prev_low < Y_curr_low and show_trendlines and Y_curr_low > prev_close_L 
        newTrendLine('pl', X_prev_low, Y_prev_low, X_curr_low, Y_curr_low)
        down_trend_line_formed:=true

if ph
    X_prev_high := X_curr_high, Y_prev_high := Y_curr_high, prev_close_H := curr_close_H
    X_curr_high := bar_index[pivLen_R], Y_curr_high := s_high[pivLen_R], curr_close_H:= s_close[pivLen_R]
    
    if Y_prev_high > Y_curr_high and show_trendlines and prev_close_H > Y_curr_high
        newTrendLine('ph', X_prev_high, Y_prev_high, X_curr_high, Y_curr_high)
        up_trend_line_formed := true


if close > Y_prev_high
    Y_prev_high:=0.000000

if close < Y_prev_low
    Y_prev_low:= 9999999999.9999


// alertcondition(up_trend_line_formed,'Up TrendLine Formed','Up TrendLine Formed')
// alertcondition(down_trend_line_formed,'Down TrendLine Formed','Down TrendLine Formed')
alertcondition(down_trend_line_formed or up_trend_line_formed,'Trendline Formed','Trendline Formed')

up_trend_line_broken = false
down_trend_line_broken = false

for x in pivot_low_array
    var line [] Down_Trend_Lines = array.new_line(tl_array_size_up)
    var label [] Down_Trend_Labels = array.new_label(tl_array_size_up)
    src = Source_tl == 'Close' ? s_close : s_low
    x.set_xy2(bar_index, SlopeOfLine(x))
    if x.get_x2() - x.get_x1() > 300
        x.delete()
    if src < line.get_y2(x)
        tl_line = line.new(line.get_x1(x), line.get_y1(x), line.get_x2(x), line.get_y2(x), color = broken_color_down, style = lineStyle_broken, width = line_width_broken,xloc = xloc.bar_index, extend = extendLine_B ? extend.right : extend.none)
        down_trend_line_broken:=true
        Down_Trend_Lines.unshift(tl_line)
        line.delete(x)
    if Down_Trend_Lines.size() > (tl_array_size_up)
        line.delete(Down_Trend_Lines.pop())

for x in pivot_high_array
    var line [] Up_Trend_Lines = array.new_line(tl_array_size_dn)
    var label [] Up_Trend_Labels = array.new_label(tl_array_size_dn)
    src = Source_tl == 'Close' ? s_close : s_high
    x.set_xy2(bar_index, SlopeOfLine(x))
    if x.get_x2() - x.get_x1() > 300
        x.delete()
    if src > line.get_y2(x)
        tl_line = line.new(line.get_x1(x), line.get_y1(x), line.get_x2(x), line.get_y2(x), color = broken_color_up, style = lineStyle_broken, width = line_width_broken,xloc = xloc.bar_index, extend = extendLine_B ? extend.right : extend.none)
        up_trend_line_broken:=true
        Up_Trend_Lines.unshift(tl_line)
        line.delete(x)
    if Up_Trend_Lines.size() > (tl_array_size_dn)
        line.delete(Up_Trend_Lines.pop())


plotshape(show_signals and up_trend_line_broken? low : na, title='Trendline Broken Up', style=shape.xcross, textcolor=color.new(color.white, 0), size=size.small, location=location.belowbar, color=broken_color_up_signal,display=  display.all - display.status_line, editable = false)
plotshape(show_signals and down_trend_line_broken? high : na, title='Trendline Broken Down', style=shape.xcross,  textcolor=color.new(color.white, 0), size=size.small, location=location.abovebar, color=broken_color_down_signal,display=  display.all - display.status_line, editable = false)

// alertcondition(up_trend_line_broken,'Up TrendLine Broken','Up TrendLine Broken')
// alertcondition(down_trend_line_broken,'Down TrendLine Broken','Down TrendLine Broken')
alertcondition(up_trend_line_broken or down_trend_line_broken,'Trendline Broken','Trendline Broken')

